package com.common.bean.handler;


import com.common.bean.execption.CheckedException;
import com.common.bean.execption.UnloginException;
import com.common.util.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.server.ServerErrorException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.io.IOException;


/**
 * 错误同意拦截
 */
@Slf4j
@RestControllerAdvice
public final class ExceptionAdviceHandler {

    private final static String SERVER_ERROR_TXT = "服务器内部错误";
    private final static String ARGUMENTS_ERROR_TXT = "参数错误";
    private final static String BAD_REQUEST_TXT = "错误的请求";

    @ExceptionHandler(value = Exception.class)
    public R unKnowExceptionHandler(Exception e) {
        return this.serverErrorHandler(e);
    }

    @ExceptionHandler(value = RuntimeException.class)
    public R runtimeExceptionHandler(RuntimeException e) {
        return this.serverErrorHandler(e);
    }

    /**
     * 空指针异常
     */
    @ExceptionHandler(NullPointerException.class)
    public R nullPointerExceptionHandler(NullPointerException e) {
        return this.serverErrorHandler(e);
    }

    /**
     * 类型转换异常
     */
    @ExceptionHandler(ClassCastException.class)
    public R classCastExceptionHandler(ClassCastException e) {
        return this.serverErrorHandler(e);
    }

    /**
     * IO异常
     */
    @ExceptionHandler(IOException.class)
    public R iOExceptionHandler(IOException e) {
        return this.serverErrorHandler(e);
    }

    /**
     * 未知方法异常
     */
    @ExceptionHandler(NoSuchMethodException.class)
    public R noSuchMethodExceptionHandler(NoSuchMethodException e) {
        return this.serverErrorHandler(e);
    }

    /**
     * 数组越界异常
     */
    @ExceptionHandler(IndexOutOfBoundsException.class)
    public R indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException e) {
        return this.serverErrorHandler(e);
    }
    /**
     * 数组越界异常
     */
    @ExceptionHandler(InvalidGrantException.class)
    public R invalidGrantExceptionHandler(IndexOutOfBoundsException e) {
        return this.invalidGrantErrorHandler(e);
    }

    /**
     * 400错误
     */
    @ExceptionHandler(value = HttpMessageNotReadableException.class)
    public R requestNotReadable(HttpMessageNotReadableException e) {
        return this.requestError(e);
    }

    /**
     * 400错误 类型不匹配
     */
    @ExceptionHandler({TypeMismatchException.class})
    public R requestTypeMismatch(TypeMismatchException e) {
        return this.argumentsError(e);
    }

    /**
     * 400错误 缺少参数
     */
    @ExceptionHandler({MissingServletRequestParameterException.class})
    public R requestMissingServletRequest(MissingServletRequestParameterException e) {
        return this.argumentsError(e);
    }

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
        return this.requestError(e);
    }

    @ExceptionHandler(UsernameNotFoundException.class)
    public R usernameNotFound(UsernameNotFoundException e) {
        return this.requestError(e);
    }

    /**
     * 405错误
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    public R request405(HttpRequestMethodNotSupportedException e) {
        return this.requestError(e);
    }

    /**
     * 406错误
     */

    @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
    public R request406(HttpMediaTypeNotAcceptableException e) {
        return this.requestError(e);

    }

    /**
     * 500错误
     */
    @ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
    public R server500(Exception e) {
        return this.serverErrorHandler(e);
    }

    @ExceptionHandler(value = HttpMediaTypeNotSupportedException.class)
    public R httpMediaTypeNotSupportedExceptionHandler(HttpMediaTypeNotSupportedException e) {
        return this.requestError(e);
    }


    /**
     * 404
     */
    @ExceptionHandler(value = NoHandlerFoundException.class)
    public R notFoundException(NoHandlerFoundException e) {
        return this.requestError(e);
    }

    @ExceptionHandler(value = ServerErrorException.class)
    public R serverErrorExceptionHandler(ServerErrorException e) {
        return this.serverErrorHandler(e);
    }


    private R serverErrorHandler(Exception e) {
        log.error(SERVER_ERROR_TXT + "：" + e.getMessage(), e);
        if(e instanceof CheckedException || e instanceof UnloginException) {
            return R.error(200, e.getMessage());
        }
        return R.error(500, SERVER_ERROR_TXT);
    }
    private R invalidGrantErrorHandler(Exception e) {
        log.error(SERVER_ERROR_TXT + "：" + e.getMessage(), e);
        return R.error(200, "密码错误");
    }

    private R argumentsError(Exception e) {
        log.error(ARGUMENTS_ERROR_TXT + "：" + e.getMessage(), e);
        return R.error(400, ARGUMENTS_ERROR_TXT);
    }

    private R requestError(Exception e) {
        log.error(BAD_REQUEST_TXT + "：" + e.getMessage(), e);
        return R.error(400, BAD_REQUEST_TXT);
    }

}
